using AvalonAdmin.Models;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.Input;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.Windows.Input;
using Ursa.Controls;

namespace AvalonAdmin.BaseViewModel
{
    /// <summary>
    /// 简化的集成视图模型
    /// </summary>
    /// <typeparam name="T">数据类型</typeparam>
    public abstract class SimpleIntegratedViewModel<T> : BaseDataViewModel<T>, ISelectionViewModel<T>, ICrudViewModel<T>
    {
        /// <summary>
        /// 按钮项集合
        /// </summary>
        public ObservableCollection<ButtonItem> ButtonItems { get; set; } = new();
        protected DialogOptions GetDialogOptions(string title, DialogMode dialogMode = DialogMode.Info, DialogButton dialogButton = DialogButton.None)
        {
            return new DialogOptions
            {
                Title = title,
                Mode = DialogMode.Info,
                Button = dialogButton,
                ShowInTaskBar = false,
                CanResize = true,
                IsCloseButtonVisible = true,
                StartupLocation = WindowStartupLocation.CenterOwner,
                CanDragMove = true
            };
        }

        #region 字段

        private SelectionViewModel<T>? _selection;
        #endregion

        #region 构造函数
        protected SimpleIntegratedViewModel()
        {
            InitializeCommands();
        }
        #endregion

        #region 选择属性
        public bool IsAllSelected
        {
            get => _selection?.IsAllSelected ?? false;
            set
            {
                if (_selection != null)
                {
                    _selection.IsAllSelected = value;
                    OnPropertyChanged();
                }
            }
        }

        public bool HasSelectedItems => _selection?.HasSelectedItems ?? false;

        public List<T> GetSelectedItems() => _selection?.GetSelectedItems() ?? new List<T>();

        public void ToggleSelectAll()
        {
            _selection?.ToggleSelectAll();
            OnPropertyChanged(nameof(IsAllSelected));
            OnPropertyChanged(nameof(HasSelectedItems));
            RefreshCommandStates();
        }

        public void SelectItem(T item)
        {
            _selection?.SelectItem(item);
            OnPropertyChanged(nameof(IsAllSelected));
            OnPropertyChanged(nameof(HasSelectedItems));
            RefreshCommandStates();
        }

        public void UpdateAllSelectedState()
        {
            _selection?.UpdateAllSelectedState();
            OnPropertyChanged(nameof(IsAllSelected));
        }
        #endregion

        #region 命令
        public ICommand QueryCommand { get; private set; } = null!;
        public ICommand ResetCommand { get; private set; } = null!;
        public ICommand AddCommand { get; private set; } = null!;
        public ICommand UpdateCommand { get; private set; } = null!;
        public ICommand DeleteCommand { get; private set; } = null!;
        public ICommand BatchDeleteCommand { get; private set; } = null!;
        public ICommand SelectAllCommand { get; private set; } = null!;

        // 导入导出命令
        public ICommand ImportCommand { get; private set; } = null!;
        public ICommand ExportCommand { get; private set; } = null!;
        public ICommand ExportTemplateCommand { get; private set; } = null!;

        // 分页命令
        public ICommand PageChangedCommand { get; private set; } = null!;
        #endregion

        #region 命令初始化
        private void InitializeCommands()
        {
            QueryCommand = new AsyncRelayCommand(QueryAsync);
            ResetCommand = new RelayCommand(Reset);
            AddCommand = new AsyncRelayCommand<T>(AddAsync, CanAdd);
            UpdateCommand = new AsyncRelayCommand<T>(UpdateAsync, CanUpdate);
            DeleteCommand = new AsyncRelayCommand<T>(DeleteAsync, CanDelete);
            BatchDeleteCommand = new AsyncRelayCommand<IEnumerable<T>>(BatchDeleteAsync, _ => HasSelectedItems);
            SelectAllCommand = new RelayCommand(ToggleSelectAll);

            // 初始化导入导出命令
            ImportCommand = new AsyncRelayCommand(ImportAsync, () =>  CanImport());
            ExportCommand = new AsyncRelayCommand(ExportAsync, () => CanExport());
            ExportTemplateCommand = new AsyncRelayCommand(ExportTemplateAsync, () =>  CanExportTemplate());

            // 初始化分页命令
            PageChangedCommand = new AsyncRelayCommand<Pagination>(OnPageChangedAsync);
        }
        #endregion

        #region 命令可执行条件
        protected virtual bool CanAdd(T? obj) => true;
        protected virtual bool CanUpdate(T? obj) => obj != null || HasSelectedModel;
        protected virtual bool CanDelete(T? obj) => obj != null || HasSelectedModel;

        // 导入导出权限控制
        protected virtual bool CanImport() => true;
        protected virtual bool CanExport() => true;
        protected virtual bool CanExportTemplate() => true;
        #endregion

        #region 抽象CRUD方法
        public abstract Task AddAsync(T? obj = default);
        public abstract Task UpdateAsync(T? obj = default);
        public abstract Task DeleteAsync(T? obj = default);
        public abstract Task BatchDeleteAsync(IEnumerable<T>? items = null);
        #endregion

        #region 虚拟导入导出方法
        /// <summary>
        /// 导入数据（子类可重写以实现具体的导入逻辑）
        /// </summary>
        protected virtual async Task ImportAsync()
        {
            // 默认实现：显示不支持导入的消息
            ShowWarning("当前页面不支持导入功能");
            await Task.CompletedTask;
        }

        /// <summary>
        /// 导出数据（子类可重写以实现具体的导出逻辑）
        /// </summary>
        protected virtual async Task ExportAsync()
        {
            // 默认实现：显示不支持导出的消息
            ShowWarning("当前页面不支持导出功能");
            await Task.CompletedTask;
        }

        /// <summary>
        /// 导出模板（子类可重写以实现具体的模板导出逻辑）
        /// </summary>
        protected virtual async Task ExportTemplateAsync()
        {
            // 默认实现：显示不支持导出模板的消息
            ShowWarning("当前页面不支持导出模板功能");
            await Task.CompletedTask;
        }
        #endregion

        #region 分页及分页处理

        private int _pageNo = 1;
        /// <summary>
        /// 当前页码
        /// </summary>
        public int PageNo
        {
            get => _pageNo;
            set => SetProperty(ref _pageNo, value);
        }

        private int _pageSize = 30;
        /// <summary>
        /// 每页大小
        /// </summary>
        public int PageSize
        {
            get => _pageSize;
            set => SetProperty(ref _pageSize, value);
        }

        private int _totalCount;
        /// <summary>
        /// 总记录数
        /// </summary>
        public int TotalCount
        {
            get => _totalCount;
            set => SetProperty(ref _totalCount, value);
        }

        private long _totalPage;
        /// <summary>
        /// 总页数
        /// </summary>
        public long TotalPage
        {
            get => _totalPage;
            set => SetProperty(ref _totalPage, value);
        }

        private string _paginationInfo = string.Empty;
        /// <summary>
        /// 分页信息显示文本
        /// </summary>
        public string? PaginationInfo
        {
            get => _paginationInfo;
            set => SetProperty(ref _paginationInfo, value);
        }
         
        /// <summary>
        /// 刷新分页信息
        /// </summary>
        public void RefreshPagination(long totalCount, int totalPage)
        {
            // 确保在UI线程上创建和更新UI控件
            TotalCount = (int)totalCount;
            TotalPage = totalPage;
            PaginationInfo = $"第 {PageNo} 页，共 {totalPage} 页，共 {totalCount} 条";
        }

        /// <summary>
        /// 处理分页变化事件
        /// </summary>
        protected virtual async Task OnPageChangedAsync(Pagination? parameter = null)
        {
            // 如果传入了分页控件参数，更新当前页码
            if (parameter is Ursa.Controls.Pagination pagination)
            {
                if (pagination.CurrentPage!=null)
                {
                    PageNo = pagination.CurrentPage.Value;
                }

                if (PageSize != pagination.PageSize)
                {
                    PageSize = pagination.PageSize;
                    PageNo = 1;
                }
            }
            await QueryAsync();
        }
         
        #endregion

        #region 重写基类方法
        protected override void OnDataChanged()
        {
            base.OnDataChanged();
            InitializeSelection();
            RefreshCommandStates();
        }

        protected override void OnSelectedModelChanged()
        {
            base.OnSelectedModelChanged();
            RefreshCommandStates();
        }
        #endregion

        #region 私有方法
        private void InitializeSelection()
        {
            if (Data != null)
            {
                _selection = new SelectionViewModel<T>(
                    Data,
                    GetIsSelected,
                    SetIsSelected);
            }
        }

        protected void RefreshCommandStates()
        {
            Dispatcher.UIThread.Post(() =>
            {
                (AddCommand as AsyncRelayCommand<T>)?.NotifyCanExecuteChanged();
                (UpdateCommand as AsyncRelayCommand<T>)?.NotifyCanExecuteChanged();
                (DeleteCommand as AsyncRelayCommand<T>)?.NotifyCanExecuteChanged();
                (BatchDeleteCommand as AsyncRelayCommand<IEnumerable<T>>)?.NotifyCanExecuteChanged();

                // 刷新导入导出命令状态
                (ImportCommand as AsyncRelayCommand)?.NotifyCanExecuteChanged();
                (ExportCommand as AsyncRelayCommand)?.NotifyCanExecuteChanged();
                (ExportTemplateCommand as AsyncRelayCommand)?.NotifyCanExecuteChanged();
            });
        }
        #endregion

        #region 抽象方法 - 选择状态
        /// <summary>
        /// 获取项目的选中状态
        /// </summary>
        /// <param name="item">项目</param>
        /// <returns>是否选中</returns>
        protected abstract bool GetIsSelected(T item);

        /// <summary>
        /// 设置项目的选中状态
        /// </summary>
        /// <param name="item">项目</param>
        /// <param name="isSelected">是否选中</param>
        protected abstract void SetIsSelected(T item, bool isSelected);
        #endregion
    }
}